package com.simpletour.qa.user.controller;

import com.simpletour.qa.common.entity.User;
import com.simpletour.qa.common.http.ObjectRestResponse;
import com.simpletour.qa.common.http.ResponseCode;
import com.simpletour.qa.common.http.ResponseMsg;
import com.simpletour.qa.common.util.BeanUtil;
import com.simpletour.qa.common.util.ReflectionUtils;
import com.simpletour.qa.user.biz.RoleBiz;
import com.simpletour.qa.user.biz.UserBiz;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.domain.Page;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Optional;

/**
 * @author zhaohw
 * @date 2018-06-20 11:21
 */
@RequestMapping(value = "users")
@RestController
public class UserController {

    @Resource
    private UserBiz userBiz;

    @Autowired
    private RoleBiz roleBiz;

    @Autowired
    protected HttpServletRequest request;

    /**
     * 新增
     * @param user
     * @param bindingResult
     * @return
     */
    @PostMapping(value = "")
    public ObjectRestResponse add(@RequestBody @Valid User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            List<FieldError> errorList = bindingResult.getFieldErrors();
            return ObjectRestResponse.builder()
                    .code(ResponseCode.PARAM_CHECK_ERROR)
                    .msg("缺少参数,新增失败")
                    .build();
        }
        try {
            userBiz.addUserWithRoleInfo(user);
        } catch (DataIntegrityViolationException e) {
            return ObjectRestResponse.builder()
                    .code(ResponseCode.USER_NAME_DUPLICATE)
                    .msg(ResponseMsg.USER_NAME_DUPLICATE)
                    .build();
        } catch (NoSuchAlgorithmException e){
            return ObjectRestResponse.builder()
                    .code(ResponseCode.SERVER_INTERNAL_ERROR)
                    .msg(ResponseMsg.SERVER_INTERNAL_ERROR)
                    .build();
        }
        return ObjectRestResponse.builder()
                .code(ResponseCode.SUCCESS)
                .msg("新增用户成功").build();
    }



    /**
     * 分页查询
     * @param page
     * @param size
     * @return
     */
    @GetMapping(value = "",produces = {"application/json;charset=UTF-8"})
    public ObjectRestResponse findByPage(Integer page,Integer size){
            if(page == null) {page = 0;}
            if(size == null) {size = 15;}
            Page<User> users = userBiz.findAllByPage(page,size);
            users.forEach(p->p.getRoles().forEach(role->role.setAuthorities(null)));
            return ObjectRestResponse.builder()
                    .code(ResponseCode.SUCCESS)
                    .result(users)
                    .build();

    }

    /**
     * 修改用户
     * @param id
     * @param user
     * @return
     */
    @PutMapping(value = "/{id}")
    public ObjectRestResponse update(@PathVariable Integer id, @RequestBody User user){
        Integer currentUserId = getCurrentUserId();
        if(!id.equals(currentUserId)){
            return ObjectRestResponse.builder()
                    .code(ResponseCode.NO_AUTHORITY)
                    .msg("只能修改自己的资料")
                    .build();
        }
        Optional<User> oldUser = userBiz.findById(id);
        if(!oldUser.isPresent()){
            return ObjectRestResponse.builder()
                    .code(ResponseCode.USER_NOT_EXIST)
                    .msg(ResponseMsg.USER_NOT_EXIST)
                    .build();
        }
        try {
            //修改用户状态需调用 users/{id}/status
            user.setStatus(oldUser.get().getStatus());
            ReflectionUtils.setPrimaryKey(user,id);
            BeanUtil.copyPropertiesIgnoreNull(user,oldUser.get());
            userBiz.save(oldUser.get());
        }catch (DataIntegrityViolationException e){
            return ObjectRestResponse.builder()
                    .code(ResponseCode.USER_NAME_DUPLICATE)
                    .msg(ResponseMsg.USER_NAME_DUPLICATE)
                    .build();
        }catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) {
            return ObjectRestResponse.builder()
                    .code(ResponseCode.SERVER_INTERNAL_ERROR)
                    .msg(ResponseMsg.SERVER_INTERNAL_ERROR)
                    .build();
        }
        return ObjectRestResponse.builder()
                .code(ResponseCode.SUCCESS)
                .msg(ResponseMsg.SUCCESS)
                .build();
    }

    /**
     * 修改用户状态(启用 禁用)
     * @param id
     * @param user
     * @return
     */
    @PutMapping(value = "/{id}/status")
    public ObjectRestResponse updateStatus(@PathVariable Integer id, @RequestBody User user){
        Optional<User> oldUser = userBiz.findById(id);
        if(!oldUser.isPresent()){
            return ObjectRestResponse.builder()
                    .code(ResponseCode.USER_NOT_EXIST)
                    .msg(ResponseMsg.USER_NOT_EXIST)
                    .build();
        }
        try {
            ReflectionUtils.setPrimaryKey(user,id);
            BeanUtil.copyPropertiesIgnoreNull(user,oldUser.get());
            userBiz.save(oldUser.get());
        }catch (DataIntegrityViolationException e){
            return ObjectRestResponse.builder()
                    .code(ResponseCode.USER_NAME_DUPLICATE)
                    .msg(ResponseMsg.USER_NAME_DUPLICATE)
                    .build();
        }catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) {
            return ObjectRestResponse.builder()
                    .code(ResponseCode.SERVER_INTERNAL_ERROR)
                    .msg(ResponseMsg.SERVER_INTERNAL_ERROR)
                    .build();
        }
        return ObjectRestResponse.builder()
                .code(ResponseCode.SUCCESS)
                .msg(ResponseMsg.SUCCESS)
                .build();
    }

    /**
     * 查询用户
     * @param id
     * @return
     */
    @GetMapping(value = "/{id}")
    public ObjectRestResponse get(@PathVariable Integer id){
        User object=  userBiz.findById(id).orElse(null);
        if(object!=null){
            object.setPassword(null);
            object.getRoles().forEach(role->role.setAuthorities(null));
        }
        return ObjectRestResponse.builder()
                .code(ResponseCode.SUCCESS)
                .result(object)
                .msg(ResponseMsg.SUCCESS)
                .build();
    }

    /**
     * 删除用户
     * @param id
     * @return
     */
    @DeleteMapping(value = "/{id}")
    public ObjectRestResponse delete(@PathVariable Integer id){
        Integer userId = getCurrentUserId();
        if(userId.equals(id)){
            return ObjectRestResponse.builder()
                    .code(ResponseCode.USER_CAN_NOT_DELETE)
                    .msg(ResponseMsg.USER_CAN_NOT_DELETE)
                    .build();
        }
        userBiz.deleteById(id);
        return ObjectRestResponse.builder()
                .code(ResponseCode.SUCCESS)
                .msg(ResponseMsg.SUCCESS)
                .build();
    }

    /**
     * 校验用户名
     * @param username
     * @return
     */
    @GetMapping(value = "username/{username}")
    public ObjectRestResponse checkUsername(@PathVariable String username){
        User user = userBiz.findUserByUsername(username.trim());
        if(null == user){
            return ObjectRestResponse.builder()
                    .code(ResponseCode.SUCCESS)
                    .build();
        }else{
            return ObjectRestResponse.builder()
                    .code(ResponseCode.USER_NAME_DUPLICATE)
                    .msg(ResponseMsg.USER_NAME_DUPLICATE)
                    .build();
        }
    }


    private User checkNeedFields(User user,User oldUser){
        if(user.getUsername() == null){
            user.setUsername(oldUser.getUsername());
        }
        if(user.getPassword() == null){
            user.setPassword(oldUser.getPassword());
        }
        return user;
    }

    private Integer getCurrentUserId(){
        String userId = request.getHeader("userId");
        return Integer.parseInt(userId);
    }
}
